#include "JsonRpcMessageSerializer.h"
#include "JsonRpcErrorCode.h"

#include "message_serialization/JsonRpcResponse.h"
#include "message_serialization/JsonRpcNotification.h"

#include <QJsonDocument>
#include <QVariant>

JsonRpcMessageSerializer::JsonRpcMessageSerializer()
{
}

QJsonObject JsonRpcMessageSerializer::serializeSuccessResponse(const QVariant& id, const QJsonObject& result)
{
    Q_ASSERT( !id.isNull() && ( id.canConvert<double>() || id.canConvert<QString>() ) );

    JsonRpcResponse successResponse(id);
    successResponse.setResult(result);

    return successResponse.toJson();
}

QJsonObject JsonRpcMessageSerializer::serializeErrorResponse(const QVariant& id, int errorCode, const QJsonValue& errorData)
{
    Q_ASSERT( !id.isNull() && ( id.canConvert<double>() || id.canConvert<QString>() ) );

    QString errorMessage = QString::fromStdString( RpcError::Code2Msg(errorCode) );
    QJsonObject errorObject = createErrorObject(errorCode, errorMessage, errorData);
    
    JsonRpcResponse errorResponse(id);
    errorResponse.setError(errorObject);

    return errorResponse.toJson();
}

QJsonObject JsonRpcMessageSerializer::serializeNotification(const QString& method, const QJsonObject& params)
{
    // Here giving a chance to modify method and params
    QString actualMethodName = method;
    if (!actualMethodName.startsWith("notifications/"))
        actualMethodName = "notifications/" + method;

    JsonRpcNotification notification(actualMethodName, params);
    return notification.toJson();
}

QByteArray JsonRpcMessageSerializer::toByteArray(const QJsonObject& jsonObject)
{
    QJsonDocument doc(jsonObject);
    return doc.toJson(QJsonDocument::Compact);
}

QJsonObject JsonRpcMessageSerializer::createErrorObject(int code, const QString& message, const QJsonValue& data) const
{
    JsonRpcResponse errResponse;
    QJsonObject error;
    error["code"] = code;
    error["message"] = message;
    if (!data.isUndefined() && !data.isNull()) {
        error["data"] = data;
    }
    
    return error;
}
